package com.ayue.clinet.mqspringboot.config;

import com.ayue.clinet.mqspringboot.constant.QueueEnum;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * RabbitMq 配置
 * simple：模式：1v1 聊天
 * work模式：抢红包（基本均摊消费、空闲的系统自动争抢）
 * 发布/订阅模式：
 *         direct:1v1
 *         fanout:群聊、群发邮件
 *         topic: 群聊（特定标签的人接收）
 *
 *
 * 延时消息：1.订单业务： 在电商/点餐中，都有下单后 30 分钟内没有付款，就自动取消订单。2.短信通知： 下单成功后 60s 之后给用户发送短信通知。3.失败重试： 业务操作失败后，间隔一定的时间进行失败重试。
 * 死信队列：
 * @author yuelinbo
 * @date 2020/3/25 11:28
 **/
@Configuration
public class RabbitMqConfig {
    /* --------------------------------------------------simple简单模式 ---------------------------------------- */
    @Bean
    public Queue simpleQueue() {
        return new Queue(QueueEnum.QUEUE_SIMPLE.getQueueName(), true);
    }

    /* --------------------------------------------------work 工作模式 ---------------------------------------- */

    @Bean
    public Queue workQueue() {
        return new Queue(QueueEnum.QUEUE_WORK.getQueueName(), true);
    }

    /* --------------------------------------------------发布订阅direct模式 ---------------------------------------- */

    /**
     * direct直连模式： 交换机
     */
    @Bean
    DirectExchange directExchange() {
        return (DirectExchange) ExchangeBuilder
                .directExchange(QueueEnum.QUEUE_DIRECT.getExchange())
                //是否持久化
                .durable(true)
                .build();
    }

    /**
     * direct直连模式： 消息队列
     */
    @Bean
    public Queue directQueue() {
        return new Queue(QueueEnum.QUEUE_DIRECT.getQueueName());
    }

    /**
     * direct直连模式：交换机绑定队列
     */
    @Bean
    public Binding directBinding(DirectExchange directExchange, Queue directQueue) {
        return BindingBuilder
                .bind(directQueue)
                .to(directExchange)
                .with(QueueEnum.QUEUE_DIRECT.getRouterKey());
    }



    /* --------------------------------------------------fanout模式 ---------------------------------------- */

    /**
     * fanout 交换机
     */
    @Bean
    FanoutExchange fanoutExchange() {
        return (FanoutExchange) ExchangeBuilder
                .fanoutExchange(QueueEnum.QUEUE_FANOUT.getExchange())
                //是否持久化
                .durable(true)
                .build();
    }

    @Bean(name = "FanoutQueueA")
    public Queue FanoutQueueA() {
        return new Queue(QueueEnum.QUEUE_FANOUT.getQueueName() + "-a");
    }

    @Bean(name = "FanoutQueueB")
    public Queue FanoutQueueB() {
        return new Queue(QueueEnum.QUEUE_FANOUT.getQueueName() + "-b");
    }

    @Bean
    public Binding FanoutBindingA(FanoutExchange fanoutExchange, @Qualifier("FanoutQueueA") Queue fanoutQueueA) {
        return BindingBuilder
                .bind(fanoutQueueA)
                .to(fanoutExchange);
        //fanout交换机没有routerKey
//                .with(QueueEnum.QUEUE_TOPIC.getRouterKey());
    }

    @Bean
    public Binding FanoutBindingB(FanoutExchange fanoutExchange, @Qualifier("FanoutQueueB") Queue fanoutQueueB) {
        return BindingBuilder
                .bind(fanoutQueueB)
                .to(fanoutExchange);
//                .with(QueueEnum.QUEUE_TOPIC.getRouterKey()+"#");
    }

    /* --------------------------------------------------topic模式 ---------------------------------------- */

    /**
     * topic 交换机
     */
    @Bean
    TopicExchange topicExchange() {
        return (TopicExchange) ExchangeBuilder
                .topicExchange(QueueEnum.QUEUE_TOPIC.getExchange())
                //是否持久化
                .durable(true)
                .build();
    }

    @Bean(name = "TopicQueueA")
    public Queue TopicQueueA() {
        return new Queue(QueueEnum.QUEUE_TOPIC.getQueueName() + "-a");
    }

    @Bean(name = "TopicQueueB")
    public Queue TopicQueueB() {
        return new Queue(QueueEnum.QUEUE_TOPIC.getQueueName() + "-b");
    }

    @Bean
    public Binding TopicBindingA(TopicExchange topicExchange, @Qualifier("TopicQueueA") Queue topicQueueA) {
        return BindingBuilder
                .bind(topicQueueA)
                .to(topicExchange)
                .with(QueueEnum.QUEUE_TOPIC.getRouterKey());
    }

    @Bean
    public Binding TopicBindingB(TopicExchange topicExchange, @Qualifier("TopicQueueB") Queue topicQueueB) {
        return BindingBuilder
                .bind(topicQueueB)
                .to(topicExchange)
                .with(QueueEnum.QUEUE_TOPIC.getRouterKey() + "#");
    }



    /* --------------------------------------------------延迟队列 ---------------------------------------- */

    @Bean(name = "delayQueue")
    public Queue queue() {
        return new Queue(QueueEnum.QUEUE_DELAY.getQueueName(), true); //队列持久
    }

    @Bean(name = "delayExchange")
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(QueueEnum.QUEUE_DELAY.getExchange(), "x-delayed-message", true, false, args);
    }

    @Bean
    public Binding bindingQueueDelayExchange(@Qualifier("delayExchange") CustomExchange delayExchange, @Qualifier("delayQueue") Queue delayQueue) {
        return BindingBuilder
                .bind(delayQueue)
                .to(delayExchange)
                .with(QueueEnum.QUEUE_DELAY.getRouterKey())
                .noargs();

    }

}
